package com.fqgj.sentry.policy.server;


import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.sentry.common.enums.RiskResultEnums;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.common.exception.enums.ErrorCodeEnums;
import com.fqgj.sentry.policy.client.PolicySetService;
import com.fqgj.sentry.policy.dao.*;
import com.fqgj.sentry.policy.entity.*;
import com.fqgj.sentry.policy.enums.ExecutorDefaultResultEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: yujianfu (mr.vencnet@gmail.com)
 * Date: 2017/7/12
 * Time: 下午5:00
 */
@Service
public class PolicySetServiceImpl implements PolicySetService {

    @Autowired
    private PcPolicySetsDao pcPolicySetsDao;
    @Autowired
    private PcExecutorDao pcExecutorDao;
    @Autowired
    private PcExecuteResultDao pcExecuteResultDao;

    @Autowired
    private PcPolicyDao pcPolicyDao;

    @Autowired
    private PcEventDao pcEventDao;

    @Autowired
    private PcRuleDao pcRuleDao;

    @Autowired
    private PcRuleColumnDao pcRuleColumnDao;

    @Autowired
    private PcRuleConditionDao pcRuleConditionDao;

    @Override
    public Long insertPolicySet(PcPolicySetsEntity pcPolicySetsEntity) {
        checkEvent(pcPolicySetsEntity.getEventId(), pcPolicySetsEntity.getAppId());
        PcPolicySetsEntity insert = pcPolicySetsDao.insert(pcPolicySetsEntity);
        Long id = pcPolicySetsEntity.getId();
        if (id == null) {
            throw new BizException(ErrorCodeEnums.internal_server_error);
        }
        setExecutorDefaultResult(id);
        return id;
    }

    @Override
    public Boolean updatePolicySet(PcPolicySetsEntity pcPolicySetsEntity) {
        return pcPolicySetsDao.updateByPrimaryKey(pcPolicySetsEntity) > 0;
    }

    @Override
    public PcPolicySetsEntity selectOneById(Long id) {
        PcPolicySetsEntity pcPolicySetsEntity = pcPolicySetsDao.selectByPrimaryKey(id);
        if (pcPolicySetsEntity == null || pcPolicySetsEntity.getDeleted()) {
            throw new BizException(ErrorCodeEnums.policy_set_is_not_exit);
        }
        return pcPolicySetsEntity;
    }

    @Override
    public List<PcPolicySetsEntity> selectList(Long appId) {
        List<PcPolicySetsEntity> pcPolicySetsEntities = pcPolicySetsDao.selectByAppIdsAndPage(appId);
        if (CollectionUtils.isEmpty(pcPolicySetsEntities)) {
            return new ArrayList<>();
        }

        return pcPolicySetsEntities;
    }

    @Override
    public Boolean deletePolicySet(Long id) {
        List<PcExecutorEntity> executorEntityList = pcExecutorDao.selectListByPolicySetId(id);

        //找到策略集下面的策略
        List<PcPolicyEntity> pcPolicyEntities = pcPolicyDao.selectPolicyByPolicySetId(id);

        if (CollectionUtils.isEmpty(pcPolicyEntities)) {

            //删除pc_executor
            pcExecutorDao.deleteByPoliceSetId(id);

            //删除pc_policy
            pcPolicyDao.deleteByPolicySetId(id);

            //删除pc_policy_sets
            pcPolicySetsDao.deleteByPrimaryKey(id);
            return true;
        }

        List<Long> policyListId = new ArrayList<>();
        pcPolicyEntities.forEach(p -> {
            policyListId.add(p.getId());
        });

        List<PcRuleEntity> pcRuleEntities = pcRuleDao.selectListByPolicyIds(policyListId);
        if (CollectionUtils.isEmpty(pcRuleEntities)) {
            //删除pc_executor
            pcExecutorDao.deleteByPoliceSetId(id);

            //删除pc_policy
            pcPolicyDao.deleteByPolicySetId(id);

            //删除pc_policy_sets
            pcPolicySetsDao.deleteByPrimaryKey(id);
            return true;
        }

        List<Long> ruleIds = new ArrayList<>();
        pcRuleEntities.forEach(r -> {
            ruleIds.add(r.getId());
        });

        try {
            //删除rule_column
            pcRuleColumnDao.deleteByRuleIds(ruleIds);

            //删除rule_condition
            pcRuleConditionDao.deleteByRuleIds(ruleIds);

            //删除rule
            pcRuleDao.deleteByRuleIds(ruleIds);

            //删除pc_executor
            pcExecutorDao.deleteByPoliceSetId(id);

            //删除pc_policy
            pcPolicyDao.deleteByPolicySetId(id);

            //删除pc_policy_sets
            pcPolicySetsDao.deleteByPrimaryKey(id);

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 根据应用ID 和  事件ID查询
     *
     * @param appId
     * @param eventId
     * @return
     */
    @Override
    public PcPolicySetsEntity selectByAppIdAndEventId(Long appId, Long eventId) {
        return pcPolicySetsDao.selectOneByEventAndApp(eventId, appId);
    }

    private void checkEvent(Long eventId, Long appId) {
        boolean isEventExist = pcPolicySetsDao.selectOneByEventAndApp(eventId, appId) != null;
        if (isEventExist) {
            throw new BizException(ErrorCodeEnums.policy_set_event_is_exit, "事件对应的策略集已存在");
        }
    }

    private void setExecutorDefaultResult(Long id) {
        PcExecuteResultEntity executePassEntity = new PcExecuteResultEntity()
                .setResult(ExecutorDefaultResultEnum.pass.getResult())
                .setResultDesc(ExecutorDefaultResultEnum.pass.getDesc())
                .setLevel(ExecutorDefaultResultEnum.pass.getLevel())
                .setResultType(RiskResultEnums.pass.getResultType())
                .setPolicySetsId(id)
                .setType(1);
        PcExecuteResultEntity executeHandlingEntity = new PcExecuteResultEntity()
                .setResult(ExecutorDefaultResultEnum.review.getResult())
                .setResultDesc(ExecutorDefaultResultEnum.review.getDesc())
                .setLevel(ExecutorDefaultResultEnum.review.getLevel())
                .setResultType(RiskResultEnums.review.getResultType())
                .setPolicySetsId(id)
                .setType(1);
        PcExecuteResultEntity executeRejectEntity = new PcExecuteResultEntity()
                .setResult(ExecutorDefaultResultEnum.reject.getResult())
                .setResultDesc(ExecutorDefaultResultEnum.reject.getDesc())
                .setLevel(ExecutorDefaultResultEnum.reject.getLevel())
                .setResultType(RiskResultEnums.reject.getResultType())
                .setPolicySetsId(id)
                .setType(1);
        pcExecuteResultDao.insert(executePassEntity);
        pcExecuteResultDao.insert(executeHandlingEntity);
        pcExecuteResultDao.insert(executeRejectEntity);
    }
}
